Micron Document
🎖️GitЯра🎖️

Node / meshtastic / Meshtastic-Android / files / core / service / src / androidHostTest / kotlin / org / meshtastic / core / service / BootCompleteReceiverTest.kt

Displaying Raw • Download

core/service/src/androidHostTest/kotlin/org/meshtastic/core/service/BootCompleteReceiverTest.kt fix/qr-error-correction (7b45f84f) Text, 8.52 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.service

Tff7b72import T7ee787android.app.Application
Tff7b72import T7ee787android.content.BroadcastReceiver
Tff7b72import T7ee787android.content.Intent
Tff7b72import T7ee787android.os.Bundle
Tff7b72import T7ee787androidx.test.core.app.ApplicationProvider
Tff7b72import T7ee787kotlinx.coroutines.CompletableDeferred
Tff7b72import T7ee787kotlinx.coroutines.CoroutineDispatcher
Tff7b72import T7ee787kotlinx.coroutines.awaitCancellation
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787kotlinx.coroutines.test.StandardTestDispatcher
Tff7b72import T7ee787kotlinx.coroutines.test.advanceTimeBy
Tff7b72import T7ee787kotlinx.coroutines.test.advanceUntilIdle
Tff7b72import T7ee787kotlinx.coroutines.test.runCurrent
Tff7b72import T7ee787kotlinx.coroutines.test.runTest
Tff7b72import T7ee787org.junit.After
Tff7b72import T7ee787org.junit.Test
Tff7b72import T7ee787org.junit.runner.RunWith
Tff7b72import T7ee787org.koin.core.context.startKoin
Tff7b72import T7ee787org.koin.core.context.stopKoin
Tff7b72import T7ee787org.koin.dsl.module
Tff7b72import T7ee787org.meshtastic.core.di.CoroutineDispatchers
Tff7b72import T7ee787org.meshtastic.core.repository.MeshPrefs
Tff7b72import T7ee787org.robolectric.RobolectricTestRunner
Tff7b72import T7ee787org.robolectric.Shadows.shadowOf
Tff7b72import T7ee787org.robolectric.annotation.Config
Tff7b72import T7ee787org.robolectric.shadow.api.Shadow
Tff7b72import T7ee787org.robolectric.shadows.ShadowBroadcastPendingResult
Tff7b72import T7ee787org.robolectric.util.ReflectionHelpers
Tff7b72import T7ee787org.robolectric.util.ReflectionHelpers.ClassParameter
Tff7b72import T7ee787java.io.IOException
Tff7b72import T7ee787kotlin.coroutines.CoroutineContext
Tff7b72import T7ee787kotlin.test.assertEquals
Tff7b72import T7ee787kotlin.test.assertFalse
Tff7b72import T7ee787kotlin.test.assertTrue

Tf0883e@RunWithTb4b4b4(Te6edf3RobolectricTestRunnerTff7b72::Te6edf3classTb4b4b4)
Tf0883e@ConfigTb4b4b4(Te6edf3sdk Tff7b72= Tff7b72[T79c0ff3T79c0ff4Tff7b72]Tb4b4b4)
Tff7b72class T56d364BootCompleteReceiverTest Tb4b4b4{

Tf0883e@After
Tff7b72fun Td2a8fftearDownTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3stopKoinTb4b4b4(Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`persisted selected address starts service exactly once after load`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3persistedAddress Tff7b72= Te6edf3CompletableDeferredTff7b72<Tffa657String?Tff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3dispatcher Tff7b72= Te6edf3StandardTestDispatcherTb4b4b4(Te6edf3testSchedulerTb4b4b4)
Te6edf3installDependenciesTb4b4b4(Te6edf3DeferredMeshPrefs Tb4b4b4{ Te6edf3persistedAddressTb4b4b4.Te6edf3awaitTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4, Te6edf3dispatcherTb4b4b4)
Tff7b72val Te6edf3application Tff7b72= Te6edf3testApplicationTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3pendingResult Tff7b72= Te6edf3dispatchBootCompletedTb4b4b4(Te6edf3BootCompleteReceiverTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3applicationTb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3assertFalseTb4b4b4(Te6edf3pendingResultTb4b4b4.Te6edf3futureTb4b4b4.Te6edf3isDoneTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3shadowOfTb4b4b4(Te6edf3applicationTb4b4b4)Tb4b4b4.Te6edf3allStartedServicesTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4)

Te6edf3persistedAddressTb4b4b4.Te6edf3completeTb4b4b4(Ta5d6ff"Ta5d6ffxAA:BB:CC:DD:EE:FFTa5d6ff"Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3assertTrueTb4b4b4(Te6edf3pendingResultTb4b4b4.Te6edf3futureTb4b4b4.Te6edf3isDoneTb4b4b4)
Tff7b72val Te6edf3startedServices Tff7b72= Te6edf3shadowOfTb4b4b4(Te6edf3applicationTb4b4b4)Tb4b4b4.Te6edf3allStartedServices
Te6edf3assertEqualsTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3startedServicesTb4b4b4.Te6edf3sizeTb4b4b4)
Te6edf3assertEqualsTb4b4b4(Te6edf3MeshServiceTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4.Te6edf3nameTb4b4b4, Te6edf3startedServicesTb4b4b4.Te6edf3singleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3componentTff7b72?.Te6edf3classNameTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`persisted no-device sentinel does not start service after load`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3persistedAddress Tff7b72= Te6edf3CompletableDeferredTff7b72<Tffa657String?Tff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3dispatcher Tff7b72= Te6edf3StandardTestDispatcherTb4b4b4(Te6edf3testSchedulerTb4b4b4)
Te6edf3installDependenciesTb4b4b4(Te6edf3DeferredMeshPrefs Tb4b4b4{ Te6edf3persistedAddressTb4b4b4.Te6edf3awaitTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4, Te6edf3dispatcherTb4b4b4)
Tff7b72val Te6edf3application Tff7b72= Te6edf3testApplicationTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3pendingResult Tff7b72= Te6edf3dispatchBootCompletedTb4b4b4(Te6edf3BootCompleteReceiverTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3applicationTb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)
Te6edf3persistedAddressTb4b4b4.Te6edf3completeTb4b4b4(Ta5d6ff"Ta5d6ffnTa5d6ff"Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3assertTrueTb4b4b4(Te6edf3pendingResultTb4b4b4.Te6edf3futureTb4b4b4.Te6edf3isDoneTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3shadowOfTb4b4b4(Te6edf3applicationTb4b4b4)Tb4b4b4.Te6edf3allStartedServicesTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`pending result finishes when persistence load times out`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3dispatcher Tff7b72= Te6edf3StandardTestDispatcherTb4b4b4(Te6edf3testSchedulerTb4b4b4)
Te6edf3installDependenciesTb4b4b4(Te6edf3DeferredMeshPrefs Tb4b4b4{ Te6edf3awaitCancellationTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4, Te6edf3dispatcherTb4b4b4)
Tff7b72val Te6edf3application Tff7b72= Te6edf3testApplicationTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3pendingResult Tff7b72= Te6edf3dispatchBootCompletedTb4b4b4(Te6edf3BootCompleteReceiverTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3applicationTb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)
Te6edf3advanceUntilIdleTb4b4b4(Tb4b4b4)

Te6edf3assertTrueTb4b4b4(Te6edf3pendingResultTb4b4b4.Te6edf3futureTb4b4b4.Te6edf3isDoneTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3shadowOfTb4b4b4(Te6edf3applicationTb4b4b4)Tb4b4b4.Te6edf3allStartedServicesTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`timeout includes time queued for IO dispatcher`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3ioDispatcher Tff7b72= Te6edf3StallingDispatcherTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3timeoutDispatcher Tff7b72= Te6edf3StandardTestDispatcherTb4b4b4(Te6edf3testSchedulerTb4b4b4)
Tff7b72var Te6edf3persistenceReadStarted Tff7b72= Tff7b72false
Tff7b72val Te6edf3meshPrefs Tff7b72= Te6edf3DeferredMeshPrefs Tb4b4b4{
Te6edf3persistenceReadStarted Tff7b72= Tff7b72true
Te6edf3awaitCancellationTb4b4b4(Tb4b4b4)
Tb4b4b4}
Te6edf3installDependenciesTb4b4b4(Te6edf3meshPrefsTb4b4b4, Te6edf3ioDispatcherTb4b4b4, Te6edf3timeoutDispatcherTb4b4b4)
Tff7b72val Te6edf3application Tff7b72= Te6edf3testApplicationTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3pendingResult Tff7b72= Te6edf3dispatchBootCompletedTb4b4b4(Te6edf3BootCompleteReceiverTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3applicationTb4b4b4)

Te6edf3assertEqualsTb4b4b4(T79c0ff1Tb4b4b4, Te6edf3ioDispatcherTb4b4b4.Te6edf3queuedTaskCountTb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3persistenceReadStartedTb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3pendingResultTb4b4b4.Te6edf3futureTb4b4b4.Te6edf3isDoneTb4b4b4)

Te6edf3advanceTimeByTb4b4b4(T79c0ff4Te6edf3_999Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3pendingResultTb4b4b4.Te6edf3futureTb4b4b4.Te6edf3isDoneTb4b4b4)

Te6edf3advanceTimeByTb4b4b4(T79c0ff1Tb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3assertTrueTb4b4b4(Te6edf3pendingResultTb4b4b4.Te6edf3futureTb4b4b4.Te6edf3isDoneTb4b4b4)
Te6edf3assertFalseTb4b4b4(Te6edf3persistenceReadStartedTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3shadowOfTb4b4b4(Te6edf3applicationTb4b4b4)Tb4b4b4.Te6edf3allStartedServicesTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`pending result finishes when persistence load fails`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3dispatcher Tff7b72= Te6edf3StandardTestDispatcherTb4b4b4(Te6edf3testSchedulerTb4b4b4)
Te6edf3installDependenciesTb4b4b4(Te6edf3DeferredMeshPrefs Tb4b4b4{ Tff7b72throw Te6edf3IOExceptionTb4b4b4(Ta5d6ff"Ta5d6ffread failedTa5d6ff"Tb4b4b4) Tb4b4b4}Tb4b4b4, Te6edf3dispatcherTb4b4b4)
Tff7b72val Te6edf3application Tff7b72= Te6edf3testApplicationTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3pendingResult Tff7b72= Te6edf3dispatchBootCompletedTb4b4b4(Te6edf3BootCompleteReceiverTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3applicationTb4b4b4)
Te6edf3runCurrentTb4b4b4(Tb4b4b4)

Te6edf3assertTrueTb4b4b4(Te6edf3pendingResultTb4b4b4.Te6edf3futureTb4b4b4.Te6edf3isDoneTb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3shadowOfTb4b4b4(Te6edf3applicationTb4b4b4)Tb4b4b4.Te6edf3allStartedServicesTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffinstallDependenciesTb4b4b4(
Te6edf3meshPrefsTb4b4b4: Te6edf3MeshPrefsTb4b4b4,
Te6edf3ioDispatcherTb4b4b4: Te6edf3CoroutineDispatcherTb4b4b4,
Te6edf3defaultDispatcherTb4b4b4: Te6edf3CoroutineDispatcher Tff7b72= Te6edf3ioDispatcherTb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3startKoin Tb4b4b4{
Te6edf3modulesTb4b4b4(
Te6edf3module Tb4b4b4{
Te6edf3single Tb4b4b4{ Te6edf3meshPrefs Tb4b4b4}
Te6edf3single Tb4b4b4{
Te6edf3CoroutineDispatchersTb4b4b4(Te6edf3io Tff7b72= Te6edf3ioDispatcherTb4b4b4, Te6edf3main Tff7b72= Te6edf3defaultDispatcherTb4b4b4, Te6edf3default Tff7b72= Te6edf3defaultDispatcherTb4b4b4)
Tb4b4b4}
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8fftestApplicationTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3Application Tff7b72=
Te6edf3ApplicationProviderTb4b4b4.Te6edf3getApplicationContextTff7b72<Te6edf3ApplicationTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3also Tb4b4b4{ Te6edf3shadowOfTb4b4b4(Tffa657itTb4b4b4)Tb4b4b4.Te6edf3clearStartedServicesTb4b4b4(Tb4b4b4) Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffdispatchBootCompletedTb4b4b4(
Te6edf3receiverTb4b4b4: Te6edf3BootCompleteReceiverTb4b4b4,
Te6edf3applicationTb4b4b4: Te6edf3ApplicationTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3ShadowBroadcastPendingResult Tb4b4b4{
Tff7b72val Te6edf3pendingResult Tff7b72=
Te6edf3ReflectionHelpersTb4b4b4.Te6edf3callStaticMethodTff7b72<Te6edf3BroadcastReceiverTb4b4b4.Te6edf3PendingResultTff7b72>Tb4b4b4(
Te6edf3ShadowBroadcastPendingResultTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4,
Ta5d6ff"Ta5d6ffcreateTa5d6ff"Tb4b4b4,
Te6edf3ClassParameterTb4b4b4.Te6edf3fromTb4b4b4(Tffa657IntTff7b72::Te6edf3classTb4b4b4.Te6edf3javaPrimitiveTypeTff7b72!!Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4,
Te6edf3ClassParameterTb4b4b4.Te6edf3fromTb4b4b4(Tffa657StringTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3ClassParameterTb4b4b4.Te6edf3fromTb4b4b4(Te6edf3BundleTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4, Te6edf3BundleTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4,
Te6edf3ClassParameterTb4b4b4.Te6edf3fromTb4b4b4(Tffa657BooleanTff7b72::Te6edf3classTb4b4b4.Te6edf3javaPrimitiveTypeTff7b72!!Tb4b4b4, Tff7b72falseTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3ReflectionHelpersTb4b4b4.Te6edf3callInstanceMethodTff7b72<Tffa657Any?Tff7b72>Tb4b4b4(
Te6edf3receiverTb4b4b4,
Ta5d6ff"Ta5d6ffsetPendingResultTa5d6ff"Tb4b4b4,
Te6edf3ClassParameterTb4b4b4.Te6edf3fromTb4b4b4(Te6edf3BroadcastReceiverTb4b4b4.Te6edf3PendingResultTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4, Te6edf3pendingResultTb4b4b4)Tb4b4b4,
Tb4b4b4)

Te6edf3receiverTb4b4b4.Te6edf3onReceiveTb4b4b4(Te6edf3applicationTb4b4b4, Te6edf3IntentTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3ACTION_BOOT_COMPLETEDTb4b4b4)Tb4b4b4)

Tff7b72return Te6edf3ShadowTb4b4b4.Te6edf3extractTb4b4b4(Te6edf3pendingResultTb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72class T56d364DeferredMeshPrefsTb4b4b4(Tff7b72private Tff7b72val Te6edf3loadDeviceAddressTb4b4b4: Te6edf3suspend Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657String?Tb4b4b4) Tb4b4b4: Te6edf3MeshPrefs Tb4b4b4{
Tff7b72override Tff7b72val Te6edf3deviceAddress Tff7b72= Te6edf3MutableStateFlowTff7b72<Tffa657String?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)

Tff7b72override Tff7b72fun Td2a8ffsetDeviceAddressTb4b4b4(Te6edf3addressTb4b4b4: Tffa657String?Tb4b4b4) Tb4b4b4{
Te6edf3deviceAddressTb4b4b4.Te6edf3value Tff7b72= Te6edf3address
Tb4b4b4}

Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffawaitDeviceAddressTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657String? Tff7b72= Te6edf3loadDeviceAddressTb4b4b4(Tb4b4b4)

Tff7b72override Tff7b72fun Td2a8ffgetStoreForwardLastRequestTb4b4b4(Te6edf3addressTb4b4b4: Tffa657String?Tb4b4b4)Tb4b4b4: Te6edf3StateFlowTff7b72<Tffa657IntTff7b72> Tff7b72= Te6edf3MutableStateFlowTb4b4b4(T79c0ff0Tb4b4b4)

Tff7b72override Tff7b72fun Td2a8ffsetStoreForwardLastRequestTb4b4b4(Te6edf3addressTb4b4b4: Tffa657String?Tb4b4b4, Te6edf3timestampTb4b4b4: Tffa657IntTb4b4b4) Tff7b72= Tffa657Unit
Tb4b4b4}

Tff7b72private Tff7b72class T56d364StallingDispatcher Tb4b4b4: Te6edf3CoroutineDispatcherTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3queuedTasks Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3RunnableTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3queuedTaskCountTb4b4b4: Tffa657Int
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3queuedTasksTb4b4b4.Te6edf3size

Tff7b72override Tff7b72fun Td2a8ffdispatchTb4b4b4(Te6edf3contextTb4b4b4: Te6edf3CoroutineContextTb4b4b4, Te6edf3blockTb4b4b4: Te6edf3RunnableTb4b4b4) Tb4b4b4{
Te6edf3queuedTasks Tff7b72+Tff7b72= Te6edf3block
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.07s